package com.cke.yang.security.app.service.impl;

import com.cke.yang.common.domain.model.SecUserDetails;
import com.cke.yang.common.infra.utils.JwtUtils;
import com.cke.yang.common.infra.utils.UserDetailsUtils;
import com.cke.yang.security.app.service.SecRoleService;
import com.cke.yang.security.domain.entity.SecRole;
import com.cke.yang.security.domain.repository.SecRoleRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 角色服务实现类
 *
 * @author yuyang
 */
@Slf4j
@Service
public class SecRoleServiceImpl implements SecRoleService {

    @Autowired
    private SecRoleRepository secRoleRepository;

    @Autowired
    private JwtUtils jwtUtils;

    @Override
    public List<SecRole> getCurrentUserRoles() {
        log.debug("获取当前用户的角色列表");

        // 获取当前登录用户ID
        Long currentUserId = UserDetailsUtils.getCurrentUserId();
        if (currentUserId == null) {
            log.warn("当前用户未登录，返回空角色列表");
            return List.of();
        }

        log.debug("当前用户ID: {}", currentUserId);

        // 通过Repository获取用户角色列表
        List<SecRole> roles = secRoleRepository.getRoleListByUserId(currentUserId);

        log.debug("当前用户角色数量: {}", roles.size());
        return roles;
    }

    @Override
    public List<SecRole> getAllRoles() {
        log.debug("获取所有角色列表");
        // 通过Repository获取所有角色列表
        List<SecRole> roles = secRoleRepository.getAllRoles();
        log.debug("系统中角色总数量: {}", roles.size());
        return roles;
    }

    @Override
    public Map<String, Object> switchCurrentRole(Long roleId) {
        log.debug("切换当前用户角色到: {}", roleId);

        // 获取当前用户详情
        SecUserDetails userDetails = UserDetailsUtils.getCurrentUserDetails();
        if (userDetails == null) {
            log.warn("当前用户未登录，无法切换角色");
            return null;
        }

        Long currentUserId = userDetails.getUserId();
        log.debug("当前用户ID: {}", currentUserId);

        // 验证用户是否拥有该角色
        List<SecRole> userRoles = secRoleRepository.getRoleListByUserId(currentUserId);
        SecRole targetRole = userRoles.stream()
                .filter(role -> role.getRoleId().equals(roleId))
                .findFirst()
                .orElse(null);

        if (targetRole == null) {
            log.warn("用户ID: {} 不拥有角色ID: {}，无法切换", currentUserId, roleId);
            return null;
        }

        // 更新用户详情中的当前角色
        userDetails.setCurrentRoleId(roleId);
        userDetails.setCurrentRoleName(targetRole.getRoleName());

        // 生成包含新角色ID的访问令牌
        String newAccessToken = jwtUtils.generateAccessToken(
                userDetails.getUserId(),
                userDetails.getUsername(),
                roleId
        );

        // 构建响应数据
        Map<String, Object> response = new HashMap<>();
        response.put("accessToken", newAccessToken);
        response.put("roleId", targetRole.getRoleId());
        response.put("roleName", targetRole.getRoleName());
        response.put("expires", System.currentTimeMillis() + jwtUtils.getAccessTokenExpiration());

        log.info("用户ID: {} 成功切换到角色: {} (ID: {})，生成新的访问令牌",
                currentUserId, targetRole.getRoleName(), roleId);
        return response;
    }

    @Override
    public SecRole getCurrentRole() {
        log.debug("获取当前用户的当前角色");

        // 获取当前用户详情
        SecUserDetails userDetails = UserDetailsUtils.getCurrentUserDetails();
        if (userDetails == null) {
            log.warn("当前用户未登录，无法获取当前角色");
            return null;
        }

        Long currentRoleId = userDetails.getCurrentRoleId();
        if (currentRoleId == null) {
            log.debug("当前用户未设置当前角色");
            return null;
        }

        // 通过Repository获取角色详情
        List<SecRole> userRoles = secRoleRepository.getRoleListByUserId(userDetails.getUserId());
        return userRoles.stream()
                .filter(role -> role.getRoleId().equals(currentRoleId))
                .findFirst()
                .orElse(null);
    }

}

